﻿using System;
using System.Collections.Generic;
using System.Linq;
using DemoApp.DataAccess;

namespace DemoApp.Model
{
    /// <summary>
    ///     Represents a source of customers in the application.
    /// </summary>
    internal class CustomerRepository : List<Customer>, ICustomerRepository
    {
        #region Fields

        private readonly ICustomerDb _db;

        #endregion // Fields

        #region Constructor

        /// <summary>
        ///     Creates a new repository of customers.
        /// </summary>
        public CustomerRepository(ICustomerDb db)
        {
            _db = db;
        }

        #endregion // Constructor

        #region Public Interface

        /// <summary>
        ///     Raised when a customer is placed into the repository.
        /// </summary>
        public event EventHandler<CustomerAddedEventArgs> CustomerAdded;

        /// <summary>
        ///     Places the specified customer into the repository.
        ///     If the customer is already in the repository, an
        ///     exception is not thrown.
        /// </summary>
        public void AddCustomer(Customer customer)
        {
            if (customer == null)
            {
                throw new ArgumentNullException("customer");
            }

            if (Contains(customer)) return;

            if (!_db.AddCustomer(customer.TotalSales, customer.FirstName,
                                 customer.LastName, customer.IsCompany, customer.Email)) return;

            Add(customer);

            if (CustomerAdded != null)
            {
                CustomerAdded(this, new CustomerAddedEventArgs(customer));
            }
        }

        /// <summary>
        ///     Returns true if the specified customer exists in the
        ///     repository, or false if it is not.
        /// </summary>
        public bool ContainsCustomer(Customer customer)
        {
            if (customer == null)
            {
                throw new ArgumentNullException("customer");
            }

            return Contains(customer);
        }


        /// <summary>
        ///     Returns a shallow-copied list of all customers in the repository.
        /// </summary>
        public IEnumerable<Customer> GetCustomers()
        {
            AddRange(_db.GetCustomers().Select(ToCustomer));

            return this;
        }

        private Customer ToCustomer(CustomerDao customer)
        {
            return Customer.CreateCustomer(customer.TotalSales,
                                           customer.FirstName,
                                           customer.LastName,
                                           customer.IsCompany,
                                           customer.Email);
        }

        #endregion // Public Interface
    }
}